<template>
  <div class="vxe-table" ref="vxeTableRef">
    <div class="vxe-table-render-wrapper" style="height: 400px">
      <div class="vxe-table-header-wrapper">
        <div class="vxe-table-header">
          <table cellspacing="0" cellpadding="0" border="0">
            <colgroup>
              <col
                :style="{ width: col.width?`${col.width}px`:`${autoColWidth}px` }"
                v-for="col in columns"
              />
              <!-- <col :style="{width:scrollBarWidth+'px'}"/> -->
            </colgroup>
            <thead>
              <tr class="vxe-header-row">
                <th class="vxe-header-col" v-for="(col,index) in columns">
                  <div class="vxe-cell">{{ col.title }}</div>
                  <div class="vxe-resizable shape" v-if="index != columns.length - 1" @mousedown="clickResize(index,$event)" @mouseup="resizeDisplay = 'none'"></div>
                </th>
                <!-- <th class="vxe-header-col header-scrollBar"></th> -->
              </tr>
            </thead>
          </table>
        </div>
      </div>
      <div class="vxe-table-body-wrapper" style="position: relative;" @scroll="handleScroll" :style="{height:`calc(400px - ${rowHeight}px)`}">
        <div class="vxe-table-body">
          <div class="vxe-body--y-space" :style="{height:tableData.length*rowHeight+'px'}"></div>
          <table cellspacing="0" cellpadding="0" border="0" :style="{top:scrollHeight+'px'}" style="position: absolute;left:0">
            <colgroup>
              <col
              :style="{ width: col.width?`${col.width}px`:`${autoColWidth}px` }"
                v-for="col in columns"
              />
            </colgroup>
            <tbody>
              <tr class="vxe-body-row"  v-for="data in filterData" :key="data.id" :name="data.id">
                <th class="vxe-body-col" v-for="(col,index) in columns">
                  <div class="vxe-cell">{{ data[col.field] }}</div>
                </th>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
    <!-- 列宽度设置标识线 -->
    <div class="vxe-table--resizable-bar" :style="{left:resizeLeft+'px',display:resizeDisplay}"></div>
  </div>
</template>

<script setup lang="ts">
const vxeTableRef = ref<HTMLDivElement>()

const columns = ref([
  { field: 'id',title:'id', width: 200},
  { field: "name", title: "name", width: 200 },
  { field: "sex", title: "sex" },
  { field: "role", title: "role" },
]);

interface TableType {
    id: number;
    name: string;
    sex: string;
    role: string;
}

let tableData:TableType[] = []
const filterData = ref<TableType[]>([])
const count = 10 //展示的行数
const rowHeight = 50 //行高
setTimeout(() => {
  // 模拟数据
  const mockList = []
  for (let index = 0; index < 500; index++) {
    mockList.push({
      id: index,
      name: 'Test' + index,
      role: 'Developer',
      sex: '男'
    })
  }
  tableData = mockList
  filterData.value = tableData.slice(0,count)
}, 100)

const autoColWidth = ref(0)
const scrollBarWidth = ref(19) //滚动条宽度
const getAutoColWidth = () => {
  let count = 0
  const width = columns.value.reduce((width,item) => {
    if(item.width){
      width = width + item.width
    }else{
      count++
    }
    return width
  },0)
  return (vxeTableRef.value?.clientWidth as number - width - scrollBarWidth.value)/count
}

let scrollHeight = 0
let scrollStart = 0
let scrollEnd = count
const handleScroll = (e:any) => {
    scrollHeight = e.target?.scrollTop
    scrollStart = Math.floor(e.target?.scrollTop/rowHeight)
    scrollEnd = scrollStart + count
    filterData.value = tableData.slice(scrollStart,scrollEnd)
}

// 展示列宽设置行
const resizeLeft= ref(0)
const resizeDisplay = ref('none')
const clickResize = (index:number,e:MouseEvent) => {
    // 当前列的前面所有列的总宽
    const sum = columns.value.slice(0,index).reduce((s,r) => {
        s = r.width?(s+r.width):(s+autoColWidth.value)
        return s
    },0)
    const col = columns.value[index]
    // 列宽度设置标识线的左偏移量
    resizeLeft.value = col.width?sum+col.width:sum+autoColWidth.value
    resizeDisplay.value = 'block'
    // 该列的最小宽度
    const minLeft = resizeLeft.value - columns.value[index].width! + 80
    // 表格左边的宽度
    const left = e.clientX - resizeLeft.value
    // 左右移动标识线，重新定位
    document.onmousemove = (me:MouseEvent) => {
        resizeLeft.value = me.clientX - left
        if(resizeLeft.value < minLeft)
            resizeLeft.value = minLeft
        document.onmouseup = () => {
            resizeDisplay.value = 'none'
            columns.value[index].width = resizeLeft.value - sum
            autoColWidth.value = getAutoColWidth()
            document.onmousemove = document.onmouseup = null
        }
    }
}


onMounted(() => {
  autoColWidth.value = getAutoColWidth()
  const dom = document.querySelector('.vxe-table')
  const observer = new ResizeObserver(entries => {
    autoColWidth.value = getAutoColWidth()
  })
  observer.observe(dom as Element)
})
</script>

<style scoped lang="scss">
.vxe-table {
    position: relative;
  .vxe-table-render-wrapper {
    border: 1px solid #e8eaec;

    .vxe-table-header-wrapper,
    .vxe-table-body-wrapper {
      text-align: left;
      overflow: auto;
      //取消滚动锚点，解决无限滚动的问题
      overflow-anchor:none;

      .vxe-table-header,
      .vxe-table-body {
        .vxe-header-row,
        .vxe-body-row {
          .vxe-header-col,
          .vxe-body-col {
            /**绘制分割线 */
            background-image: linear-gradient(#e8eaec, #e8eaec),
              linear-gradient(#e8eaec, #e8eaec);
            background-repeat: no-repeat;
            background-size: 1px 100%, 100% 1px;
            background-position: 100% 100%;

          }

          .vxe-header-col{
             position: relative;
          }

          .vxe-cell {
            padding-left: 10px;
            padding-right: 10px;
            word-break: break-all;
          }

          .vxe-resizable{
            position: absolute;
            bottom: 0;
            width: 14px;
            height: 100%;
            right: -7px;
            z-index: 1;
            cursor: col-resize;
          }

          .click-resizable{
             background-image: linear-gradient(#165dff, #165dff),
              linear-gradient(#e8eaec, #e8eaec);
          }
        }

        .vxe-header-row {
          background-color: #f8f8f9;
          height: 50px;
          line-height: 50px;
        }

        .vxe-body-row {
          background-color: #fff;
          height: 50px;
          line-height: 50px;
        }

        .vxe-body--y-space{
          width: 100%;
          float: left;
        }
      }
    }
  }
  .vxe-table--resizable-bar{
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 100%;
    background-color: #5281ee;
    z-index: 9;
    display: none;
  }
}
</style>
